package com.gitee.shoes.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gitee.shoes.crawler.bean.*;
import com.gitee.shoes.dto.ProductBuyNowDto;
import com.gitee.shoes.dto.ProductDetailDto;
import com.gitee.shoes.dto.ProductSoldListDto;
import com.gitee.shoes.entity.*;
import com.gitee.shoes.exception.BadRequestException;
import com.gitee.shoes.dto.ProductSoldQuery;
import com.gitee.shoes.enumeration.PlatformEnum;
import com.gitee.shoes.enumeration.TradeType;
import com.gitee.shoes.properties.ProductProperties;
import com.gitee.shoes.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.LongAdder;
import java.util.stream.Collectors;

/**
 * @author LYH
 */
@Service
@RequiredArgsConstructor
public class ProductServiceImpl implements ProductService {

    private final IProductBaseService productBaseService;
    private final IProductImageService productImageService;
    private final IProductSalePropertyService productSalePropertyService;
    private final IProductBuyNowService productBuyNowService;
    private final IProductSoldRecordService productSoldService;
    private final ProductProperties productProperties;


    @Override
    public ProductDetailDto getProductDetailWithRequest(PlatformEnum platform, String platformId, String styleId, ApiProduct customApiProduct) {
        ProductBase productBase = productBaseService.getOneByPlatformAndPlatformIdAndStyleId(platform, platformId, styleId);
        if (productBase == null) {
            return getProductDetailFromRequest(platform, platformId, styleId, customApiProduct);
        } else {
            if (BooleanUtil.isTrue(productBase.getIgnoreMark())) {
                ProductProperties.CrawlerProperties crawler = productProperties.getCrawler();
                int clearIgnoreMarkPeriod = crawler.getClearIgnoreMarkPeriod();
                if (clearIgnoreMarkPeriod != 0 &&
                        productBase.getIgnoreMarkTime().plusHours(clearIgnoreMarkPeriod).isBefore(LocalDateTime.now())) {
                    productBaseService.removeById(productBase.getId());
                    return getProductDetailFromRequest(platform, platformId, styleId, customApiProduct);
                }
            }
        }
        return new ProductDetailDto().setProduct(productBase).setImageList(productImageService.findAllByProductId(productBase.getId()))
                .setSalePropertyList(productSalePropertyService.findAllByProductId(productBase.getId()));
    }

    @Override
    public List<ProductBuyNowDto> getBuyNowWithRequest(Long productId) {
        Map<PlatformEnum, ProductBuyNowDto> result = new HashMap<>();
        ProductBase productBase = productBaseService.getById(productId);
        PlatformEnum platform = productBase.getPlatform();
        String article = productBase.getArticle();

        if (!platform.isAllowSearch()) {
            throw new BadRequestException("不支持该平台检索");
        }

        result.put(platform, getBuyNowInfo(productBase));

        // 同主货号
        List<ProductBase> otherProductBases = productBaseService.findAllByArticle(article);
        otherProductBases.removeIf(e -> e.getId().equals(productId));
        Map<PlatformEnum, ProductBuyNowDto> finalResult = result;
        otherProductBases.forEach(e -> finalResult.put(e.getPlatform(), getBuyNowInfo(e)));

        // 未入库
        PlatformEnum[] platforms = PlatformEnum.values();
        for (PlatformEnum pf : platforms) {
            if (pf.isAllowBuyNowPrice() && !result.containsKey(pf)) {
                boolean isShihuo = PlatformEnum.shihuo.equals(pf);
                int page = 0;
                if (isShihuo) {
                    page = 1;
                }
                ApiProductList apiProductList = pf.getRequest().productList(article, page, 20, null, null);
                List<ApiProduct> itemList = apiProductList.getItemList();
                if (CollUtil.isNotEmpty(itemList) && itemList.size() == 1) {
                    ApiProduct productItem = itemList.get(0);
                    ProductDetailDto productDetailDto;
                    ApiProduct customApiProduct = null;
                    if (isShihuo) {
                        // 识货详情没有主货号
                        customApiProduct = new ApiProduct().setLogoUrl(productItem.getLogoUrl())
                                .setTitle(productItem.getTitle()).setArticle(article).setStyleId(productItem.getStyleId());
                    }
                    productDetailDto = getProductDetailWithRequest(pf, productItem.getMainId(), productItem.getStyleId(), customApiProduct);
                    ProductBase product = productDetailDto.getProduct();
                    result.put(product.getPlatform(), getBuyNowInfo(product));
                } else {
//                    result.put(pf, new ProductBuyNowDto());
                    // 没有查找到，忽略，避免下次查找
                    ProductBase product = new ProductBase().setPlatform(pf).setPlatformId(IdUtil.simpleUUID()).setArticle(article)
                            .setIgnoreMark(true).setIgnoreMarkTime(LocalDateTime.now());
                    productBaseService.save(product);
                }
            }
        }
        result = MapUtil.removeNullValue(result);
        return CollUtil.newArrayList(result.values());
    }

    @Override
    public ProductSoldListDto getSoldWithRequest(ProductSoldQuery productSoldQuery) {
        Long productId = productSoldQuery.getProductId();
        Integer current = productSoldQuery.getCurrent();
        String size = productSoldQuery.getSize();
        ProductBase productBase = productBaseService.getById(productId);
        getSoldWithRequest0(productBase, 2);
        // 同主货号
        List<ProductBase> otherProductBases = productBaseService.findAllByArticle(productBase.getArticle());
        Map<Long, String> productIdNameMap = otherProductBases.stream().filter(e ->
                productSoldQuery.getPlatform() == null || e.getPlatform().equals(productSoldQuery.getPlatform()))
                .collect(Collectors.toMap(ProductBase::getId, e -> e.getPlatform().getZhText()));
        otherProductBases.removeIf(e -> e.getId().equals(productId));
        for (ProductBase otherProductBase : otherProductBases) {
            PlatformEnum platform = otherProductBase.getPlatform();
            if (!platform.isAllowSoldRecord()) {
                continue;
            }
            getSoldWithRequest0(otherProductBase, 4);
        }
        IPage<ProductSoldRecord> page = productSoldService.page(new Page<ProductSoldRecord>().setCurrent(current)
                .setSize(20), Wrappers.<ProductSoldRecord>lambdaQuery().in(ProductSoldRecord::getProductId, productIdNameMap.keySet())
                .eq(StrUtil.isNotEmpty(size), ProductSoldRecord::getSize, size)
                .orderByDesc(ProductSoldRecord::getTransTime).orderByAsc(ProductSoldRecord::getId));
        LocalDateTime now = LocalDateTime.now();
        page.getRecords().stream().forEach(e -> {
            LocalDateTime transTime = e.getTransTime();
            if (transTime.plusMinutes(1).isAfter(now)) {
                e.setTransTimeFormat("刚刚");
            } else if (transTime.plusHours(1).isAfter(now)) {
                long l = Duration.between(transTime, now).toMinutes();
                e.setTransTimeFormat(l + "分钟前");
            } else if (transTime.plusDays(1).isAfter(now)) {
                long l = Duration.between(transTime, now).toHours();
                e.setTransTimeFormat(l + "小时前");
            } else if (transTime.plusWeeks(1).isAfter(now)) {
                long l = Duration.between(transTime, now).toDays();
                e.setTransTimeFormat(l + "天前");
            } else {
                String l = DateUtil.format(transTime, DatePattern.NORM_DATE_PATTERN);
                e.setTransTimeFormat(l);
            }
            String platformName = productIdNameMap.get(e.getProductId());
            e.setPlatformName(platformName);
        });
        return new ProductSoldListDto().setSoldList(page.getRecords());
    }

    public void getSoldWithRequest0(ProductBase productBase, Integer requestPage) {
        Long productId = productBase.getId();
        // 上次更新销售记录时间
        LocalDateTime lastUpdateSoldTime = productBase.getLastUpdateSoldTime();
        ProductProperties.CrawlerProperties crawler = productProperties.getCrawler();
        int soldUpdatePeriod = crawler.getSoldUpdatePeriod();
        if (soldUpdatePeriod == 0) {
            return;
        } else if (lastUpdateSoldTime == null || lastUpdateSoldTime.plusHours(soldUpdatePeriod).isBefore(LocalDateTime.now())) {
            List<ProductSoldRecord> oldSolds = productSoldService.findAllByProductIdAndOrderByTimeDescAndLimit(productId, 3);
            List<String> oldSoldIds = oldSolds.stream().map(ProductSoldRecord::getRecordId).collect(Collectors.toList());
            LongAdder la = null;
            if (requestPage != null) {
                la = new LongAdder();
                la.add(requestPage);
            }
            requestAndSaveSold(productBase, oldSoldIds.isEmpty() ? null : Collections.synchronizedList(oldSoldIds), la,
                    null, true);
            productBaseService.updateById(productBase.setLastUpdateSoldTime(LocalDateTime.now()));
        }
    }

    private void requestAndSaveSold(ProductBase productBase, List<String> existSoldIds, LongAdder requestPage, String lastId,
                                    boolean asyncWhenSecondPage) {
        if (existSoldIds != null && existSoldIds.isEmpty()) {
            return;
        }
        if (requestPage != null && requestPage.intValue() <= 0) {
            return;
        }
        Long productId = productBase.getId();
        PlatformEnum platform = productBase.getPlatform();
        String platformId = productBase.getPlatformId();
        String styleId = productBase.getStyleId();
        ApiProductLastSoldList apiProductLastSoldList = platform.getRequest()
                .productLastSoldList(platformId, styleId, null, lastId);
        List<ApiProductLastSold> lastSoldList = apiProductLastSoldList.getLastSoldList();
        if (StrUtil.isEmpty(apiProductLastSoldList.getLastId()) || lastSoldList.isEmpty()) {
            return;
        }
        List<ProductSoldRecord> productSoldList = new ArrayList<>();
        lp:
        for (ApiProductLastSold lastSold : lastSoldList) {
            if (existSoldIds != null && existSoldIds.isEmpty()) {
                break lp;
            }
            String soldId = lastSold.getSoldId();
            // 匹配到是历史数据
            if (existSoldIds != null) {
                for (int i = 0; i < existSoldIds.size(); i++) {
                    if (existSoldIds.get(i).equals(soldId)) {
                        existSoldIds.remove(i);
                        continue lp;
                    }
                }
            }

            productSoldList.add(new ProductSoldRecord().setPrice(lastSold.getPrice()).setProductId(productId)
                    .setRecordId(lastSold.getSoldId()).setSize(lastSold.getSize())
                    .setTransTime(lastSold.getTime()));
        }
        productSoldService.saveBatch(productSoldList);
        requestPage.decrement();
        if (asyncWhenSecondPage) {
            ThreadUtil.execute(() -> {
                requestAndSaveSold(productBase, existSoldIds, requestPage, apiProductLastSoldList.getLastId(), false);
            });
        } else {
            requestAndSaveSold(productBase, existSoldIds, requestPage, apiProductLastSoldList.getLastId(), false);
        }
    }

    private ProductBuyNowDto getBuyNowInfo(ProductBase productBase) {
        if (BooleanUtil.isTrue(productBase.getIgnoreMark())) {
            return null;
        }
        PlatformEnum platform = productBase.getPlatform();
        List<ProductBuyNow> dbProductBuyNows = listBuyNowWithRequest(productBase);
        return new ProductBuyNowDto().setLogoUrl(productBase.getLogoUrl()).setBuyNowList(dbProductBuyNows)
                .setName(platform.getZhText()).setPlatform(platform);

    }

    private List<ProductBuyNow> listBuyNowWithRequest(ProductBase productBase) {
        Long productId = productBase.getId();
        PlatformEnum platform = productBase.getPlatform();
        String platformId = productBase.getPlatformId();
        String styleId = productBase.getStyleId();
        LocalDateTime lastUpdateBuyNowTime = productBase.getLastUpdateBuyNowTime();
        List<ProductBuyNow> productBuyNows = productBuyNowService.findAllByProductId(productId);
        ProductProperties.CrawlerProperties crawler = productProperties.getCrawler();
        int buyNowPriceUpdatePeriod = crawler.getBuyNowPriceUpdatePeriod();
        if (buyNowPriceUpdatePeriod == 0 || (lastUpdateBuyNowTime != null && lastUpdateBuyNowTime
                .plusHours(buyNowPriceUpdatePeriod).isAfter(LocalDateTime.now()))) {
            // 1小时同步最新价格
            return productBuyNows;
        }


        List<ApiProductSize> productSizeList = null;
        if (PlatformEnum.du.equals(platform)) {
            List<ProductSaleProperty> productSalePropertyList = productSalePropertyService.findAllByProductId(productId);
            productSizeList = productSalePropertyList.stream().map(e -> new ApiProductSize().setPropertyValueId(e.getPropertyValueId())
                    .setSize(e.getSize()).setSkuId(e.getSkuId())).collect(Collectors.toList());
        }

        ApiProductBuyNowList productBuyNowList = platform.getRequest()
                .productBuyNowList(platformId, styleId, productSizeList);
        List<ApiProductBuyNow> buyNowList = productBuyNowList.getBuyNowList();
        if (CollUtil.isNotEmpty(buyNowList)) {
            productBuyNowService.removeByProductId(productId);
            productBuyNows = buyNowList.stream().map(e ->
                    new ProductBuyNow().setProductId(productId).setPrice(e.getMinSalePrice()).setSize(e.getSize())
                            .setTradeTypeName(e.getTradeTypeName()).setTradeType(TradeType.newInstance(e.getTradeType())))
                    .collect(Collectors.toList());
            productBuyNowService.saveBatch(productBuyNows);
        }

        productBaseService.updateById(productBase.setLastUpdateBuyNowTime(LocalDateTime.now()));
        return productBuyNows;
    }

    private ProductDetailDto getProductDetailFromRequest(PlatformEnum platform, String platformId, String styleId, ApiProduct customApiProduct) {
        ApiProduct apiProduct = platform.getRequest().productDetail(platformId, styleId);
        List<ProductImage> productImages = Collections.emptyList();
        List<ProductSaleProperty> productSalePropertyList = Collections.emptyList();
        ProductBase productBase = new ProductBase().setPlatform(platform)
                .setPlatformId(platformId)
                .setArticle(apiProduct.getArticle())
                .setAuthPrice(apiProduct.getAuthPrice())
                .setTitle(apiProduct.getTitle())
                .setBrandName(apiProduct.getBrandName())
                .setSellDate(apiProduct.getSellDate())
                .setLogoUrl(apiProduct.getLogoUrl())
                .setStyleId(apiProduct.getStyleId());

        if (customApiProduct != null) {
            if (StrUtil.isEmpty(productBase.getArticle())) {
                productBase.setArticle(customApiProduct.getArticle());
            }
            if (StrUtil.isEmpty(productBase.getTitle())) {
                productBase.setTitle(customApiProduct.getTitle());
            }
            if (StrUtil.isEmpty(productBase.getLogoUrl())) {
                productBase.setLogoUrl(customApiProduct.getLogoUrl());
            }
            if (StrUtil.isEmpty(productBase.getStyleId())) {
                productBase.setStyleId(customApiProduct.getStyleId());
            }
        }
        productBaseService.save(productBase);

        List<String> imageList = apiProduct.getImageList();
        if (CollUtil.isNotEmpty(imageList)) {
            productImages = new ArrayList<>();
            for (int i = 0; i < imageList.size(); i++) {
                productImages.add(new ProductImage().setProductId(productBase.getId()).setImageUrl(imageList.get(i)).setSort(i));
            }
            productImageService.saveBatch(productImages);
        }

        List<ApiProductSize> sizeList = apiProduct.getSizeList();
        if (CollUtil.isNotEmpty(sizeList)) {
            productSalePropertyList = new ArrayList<>();
            for (int i = 0; i < sizeList.size(); i++) {
                ApiProductSize productSize = sizeList.get(i);
                productSalePropertyList.add(new ProductSaleProperty().setProductId(productBase.getId()).setSize(productSize.getSize())
                        .setSkuId(productSize.getSkuId()).setPropertyValueId(productSize.getPropertyValueId()));
            }
            productSalePropertyService.saveBatch(productSalePropertyList);
        }
        return new ProductDetailDto().setProduct(productBase).setImageList(productImages).setSalePropertyList(productSalePropertyList);
    }
}
